home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 001_100 / DISK0041 / DISK0041.ZIP / MSFILE.ASM < prev    next >
Assembly Source File  |  1984-12-08  |  31KB  |  1,103 lines

  1.     public    bufpnt, buff, fcb, cpfcb, chrcnt, fixfcb, init, init1,
  2.     public    gofil, outbuf, ptchr, gtchr, gtnfil, getfil, filbuf,
  3.     public    encode, decode, nulref, nulr, decbuf, errpack, rptq,
  4.     public    origr, rptct, rptval, clrfln, cxmsg, biterr, intmsg,
  5.     public    rtpos, erpos,rppos, stpos,nppos,rprpos,nrtpos,sppos,
  6.     public    kbpos,perpos,frpos, prtscr
  7.     include msdefs.h
  8.  
  9. rptmin    equ    3        ; At least 3 of same char in a row.
  10.  
  11. ; equates for screen positioning
  12. scrfln    equ    0316H        ; Place for file name.
  13. scrkb    equ    0416H        ; Place for percent transferred.
  14. scrper    equ    0516H        ; Place for Kbytes transferred.
  15. scrst    equ    0616H        ; Place for status.
  16. scrnp    equ    0816H        ; Place for number of packets.
  17. scrnrt  equ    0916H        ; Place for number of retries.
  18. screrr  equ    0A16H        ; Place for error msgs. 
  19. scrhi    equ    0B16H        ; Err when 8th bit is on.
  20. scrfr    equ    0B16H        ; Rename file.
  21. scrint    equ    0B16H        ; Acknowledge interrupt. [20b]
  22. scrsp    equ    0C00H        ; Place for send packet.
  23. scrrp    equ    0E00H        ; Place for receive packet.
  24. scrrpr    equ    1100H        ; Prompt when Kermit ends.
  25.  
  26.  
  27.  
  28. datas    segment    public 'datas'
  29.     extrn    data:byte, flags:byte, trans:byte, pack:byte, hierr:byte
  30.     extrn    dosnum:byte
  31.  
  32. outlin  db    cr,lf,cr,lf
  33.         db      cr,lf,'           File name:'
  34.         db      cr,lf,'  KBytes transferred:'
  35.         db      cr,lf
  36.         db      cr,lf
  37.         db      cr,lf
  38.         db      cr,lf,'   Number of packets:'
  39.         db      cr,lf,'   Number of retries:'
  40.         db      cr,lf,'          Last error: None'
  41.         db      cr,lf,'        Last warning: None'
  42.         db      '$'
  43.  
  44. ermes4  db    'Unable to rename file$'
  45. erms10  db    '?Unable to receive data$'
  46. erms11  db    '?Disk full$'
  47. erms12    db    '?Unable to create file$'
  48. erms17  db    'Record length exceeds size of buffer$'
  49. infms5  db    'Renaming file to $'
  50. infms7    db    'File interrupt$'
  51. infms8    db    'File group interrupt$'
  52. hibit    db    'Warning - Non Ascii char$'
  53. crlf    db    cr,lf,'$'
  54. printer    db    0,'PRN        '
  55. spchar    db    24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  56.     db    3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H
  57. spclen    equ    $-spchar    ; Number of special chars.
  58. spchar2    db    24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  59.     db    7BH,7DH,5FH,5EH,7EH,60H
  60. spc2len    equ    $-spchar2
  61. next    db    0FFH        ; No next character just yet.
  62. rptval    db    0        ; Repeated character.
  63. rptct    db    1        ; Number of times it's repeated.
  64. rptq    db    drpt        ; Repeat prefix.
  65. origr    db    drpt        ; Original repeat prefix.
  66. temp1    dw    ?        ; Temporary storage.
  67. temp2    dw    ?
  68. oloc    dw    0        ; Original buffer location. [21c]
  69. osiz    dw    0        ; Original buffer size. [21c]
  70. chrcnt  dw    ?        ; Number of chars in the file buffer.
  71. outpnt  dw    ?        ; Position in packet.
  72. bufpnt  dw    ?        ; Position in file buffer.
  73. fdtpnt    dw    ?        ; Pointer to within our file. 
  74. fcbptr  dw    ?        ; Position in FCB.
  75. cbfptr  dw    ?        ; Position in character buffer.
  76. filsiz    dw    0        ; Double word for filesize (in bytes.)
  77.     dw    0
  78. ofilsz    dw    0        ; Original file size percent adjusted (/100).
  79. tfilsz    dw    0        ; Bytes transferred.
  80.     dw    0
  81. oldper    dw    ?        ; old percentage
  82. oldkbt    dw    ?        ; old KB transferred.
  83. wrpmsg    db    ?        ; non-zero if we wrote percent message
  84. percnt    dw    100        ; Number to divide by for a percent.
  85. bufhex    dw    80H
  86. permsg    db    cr,' Percent transferred:$'
  87. cxzhlp    db    '^X cancels file, ^Z cancels batch'
  88.     db    ', ^E aborts protocol'
  89.     db    ', ^C quits'
  90.     db    ', Return retries'
  91.     db    '$'
  92. asmsg    db    ' AS '
  93. asmln    equ    $-asmsg
  94. filbuf  db    60H DUP(?)    ; Character buffer.
  95. buff    db    dmasiz DUP(?)    ; Use as our DTA.
  96. fcb    db    fcbsiz DUP(?)    ; Use as our FCB.
  97. cpfcb    db    fcbsiz DUP(?)    ; Save FCB in case of "*".   [7]
  98. decbuf    db    dmasiz DUP(?)    ; For decoding incoming data.
  99. datas    ends
  100.  
  101. code    segment    public
  102.     extrn    spack:near, cmblnk:near, locate:near, nout:near
  103.     extrn    putmod:near, poscur:near, clearl:near, fcbcpy:near
  104.     assume  cs:code,ds:datas
  105.  
  106. ; Position cursor for an error message.
  107.  
  108. ERPOS    PROC     NEAR
  109.     cmp flags.xflg,1    ; Packet header seen? [21c start] 
  110.     jne erp0        ; No, do as normal. 
  111.     mov dx,offset crlf
  112.     mov ah,prstr
  113.     int dos
  114.     ret
  115. erp0:    mov dx,screrr
  116.     jmp poscur
  117. ERPOS    ENDP
  118.  
  119. ; Position cursor for number of retries message.
  120.  
  121. RTPOS    PROC     NEAR
  122.     cmp flags.xflg,1    ; Packet header seen? [21c]
  123.     jne rtp0        ; No, do as normal.
  124.     ret
  125. rtp0:    mov dx,scrnrt
  126.     jmp poscur
  127. RTPOS    ENDP
  128.  
  129. ; Reassure user that we acknowledge his ^X/^Z.
  130.  
  131. INTMSG    PROC    NEAR
  132.     cmp flags.xflg,0    ; Writing to screen?
  133.     jne int1        ; Yes. Don't do anything.
  134.     mov dx,scrint
  135.     call poscur
  136.     call clearl
  137.     mov dx,offset infms7    ; File interrupted?
  138.     cmp flags.cxzflg,'X'    ; Yes. 
  139.     je int0
  140.     mov dx,offset infms8    ; File group interrupted.
  141. int0:   mov ah,prstr
  142.         int dos
  143. int1:    ret
  144. INTMSG    ENDP
  145.  
  146. ; Print err message that found a non-standard-Ascii char in the file.
  147.  
  148. BITERR    PROC    NEAR
  149.     cmp flags.remflg,0    ; remote mode?
  150.     jne biter1        ; yes, no printing.
  151.     push bx
  152.     mov dx,scrhi
  153.     call poscur
  154.     call clearl
  155.     mov ah,prstr
  156.     mov dx,offset hibit
  157.     int dos
  158.     pop bx
  159. biter1:    ret
  160. BITERR    ENDP        
  161.  
  162. ;  Clear out message about interrupted file.
  163.  
  164. CXMSG    PROC    NEAR
  165.     cmp flags.xflg,0    ; Writing to screen?
  166.     jne cxm0        ; Yes. Don't do anything.
  167.     mov dx,scrint
  168.     call poscur
  169.     call clearl
  170. cxm0:    ret
  171. CXMSG    ENDP
  172.  
  173. ;  Clear out the old filename on the screen. 
  174.  
  175. CLRFLN    PROC    NEAR
  176.     mov dx,scrfln
  177.     call poscur
  178.     call clearl        ; Clear to end of line. [19a]
  179.     ret
  180. CLRFLN    ENDP
  181.  
  182. ; some random screen positioning functions
  183. kbpos:    mov dx,scrkb        ; KBytes transferred.
  184.     call poscur
  185.     jmp clearl
  186. perpos:    mov dx,scrper        ; Percent transferred.
  187.     call poscur
  188.     jmp clearl
  189. frpos:    mov dx,scrfr        ; Say renamed file.
  190.     call poscur
  191.     jmp clearl
  192. stpos:    mov dx,scrst        ; Print status of file transfer.
  193.     call poscur
  194.     jmp clearl
  195. nppos:    mov dx,scrnp        ; Number of packets sent.
  196.     jmp poscur
  197. rprpos:    mov dx,scrrpr        ; Reprompt position.
  198.     jmp poscur
  199. nrtpos:    mov dx,scrnrt        ; Number of retries.
  200.     jmp poscur
  201. sppos:    mov dx,scrsp        ; Send packet location.
  202.     jmp poscur
  203. rppos:    mov dx,scrrp        ; Receive packet location.
  204.     jmp poscur
  205.  
  206.  
  207.  
  208. ;    Initialize buffers and clear line.
  209.  
  210. INIT    PROC    NEAR
  211.     call cmblnk
  212.     call locate
  213.     mov ah,prstr        ; Put statistics headers on the screen.
  214.     mov dx,offset outlin
  215.     int dos
  216.     mov dx,offset cxzhlp
  217.     call putmod        ; write mode line
  218.     mov wrpmsg,0        ; haven't printed the messsage yet.
  219.     call init1
  220.     ret
  221. INIT    ENDP
  222.  
  223. INIT1    PROC    NEAR
  224.     mov chrcnt,dmasiz           ; Number of chars left.
  225.     mov bufpnt,offset buff           ; Addr for beginning.
  226.     mov hierr,0
  227.     ret
  228. INIT1    ENDP
  229.  
  230. ;    Output the chars in a packet.
  231.  
  232. ; Called with AX = size of the data, BX = address of source.
  233.  
  234. FILEIO    PROC    NEAR     
  235. ptchr:  mov cx,ax
  236.     mov ax,offset outbuf    ;Where to put data when buffer gets full.
  237.     jmp decode
  238.  
  239. ; CX = Size of data, BX = Address of data, AX = Routine to call to
  240. ; dump data.
  241.  
  242. decode: push si
  243.     push di
  244.     push es
  245.     push dx
  246.     push ax
  247.     mov ax,ds
  248.     mov es,ax
  249.     pop ax
  250.     mov si,bx        ; Source of data.
  251.     mov bx,ax        ; Coroutine to call.
  252.     mov di,bufpnt        ; Destination of data.
  253.     mov dh,0        ; assume no quote char
  254.     cmp trans.ebquot,'N'    ; no quoting?
  255.     je decod1        ; yes, keep going
  256.     cmp trans.ebquot,'Y'    ; or not doing it?
  257.     je decod1        ; yes, keep going
  258.     mov dh,trans.ebquot    ; otherwise use quote char
  259.  
  260. decod1:    mov rptct,0        ; Reset.
  261.     mov rptval,0        ; Ditto.
  262.     dec cx
  263.     jge dcod11        ; More data.
  264.     jmp decod6        ; Else, we're through.
  265. dcod11:    dec chrcnt        ; Decrement number of chars in dta.
  266.     jns decod2        ; Continue if space left.
  267.     push cx
  268.     push dx
  269.     push bx
  270.     call bx            ; Output it if full.
  271.      jmp decod5        ;  Error return if disk is full.
  272.      nop
  273.     pop bx
  274.     pop dx
  275.     pop cx
  276.     mov di,bufpnt
  277. decod2:    cmp rptct,0        ; Doing a repeat?
  278.     je dcod20        ; No, so go get a character.
  279.     mov ah,0
  280.     mov al,rptval        ; Get the character we're repeating.
  281.     jmp decod4        ; And write it out to the file.
  282. dcod20:    lodsb            ; Pick up a char.
  283.     cmp rptq,0        ; Doing repeat quoting?
  284.     je dcod21        ; Nope, skip this part.
  285.     cmp al,rptq        ; Did we pick up the repeat quote char?    
  286.     jne dcod21        ; No, continue processing it.
  287.     lodsb            ; Get the size.
  288.     dec cx            ; Modify buffer count.
  289.     sub al,20H        ; Was made printable.
  290.     mov rptct,al        ; Remember how many repetitions.
  291.     lodsb            ; Get the char to repeat.
  292.     dec cx            ; Modify buffer count.
  293. dcod21:    mov ah,00H        ; Assume no 8-bit quote char. [21b start]
  294.     cmp al,dh        ; This the 8-bit quot char?
  295.     jne decod3
  296.     lodsb            ; Get the real character.
  297.     dec cx            ; Decrement # chars in packet
  298.     mov ah,80H        ; Turn on 8-bit quot char flag. [21b end] 
  299. decod3: cmp al,trans.squote    ; Is it the quote char? [21b] [21c]
  300.     jne decod4        ; If not proceed.
  301.     lodsb            ; Get the quoted character
  302.     dec cx            ; Decrement # of chars in packet.
  303.     or ah,al        ; save parity (combine with prefix)
  304.     and ah,80h        ; only parity
  305.     and al,7FH        ; Turn off the parity bit.
  306.     cmp al,trans.squote    ; Is it the quote char? [21c]
  307.     je decod4        ; If so just go write it out.
  308.     cmp al,dh        ; This the 8-bit quot char?
  309.     je  decod4        ; If so, just go write it out
  310.     cmp al,rptq        ; Is is the repeat quote character?
  311.     je decod4        ; If so, just write it out.
  312.     add al,40H        ; Make it a control char again.
  313.     and al,7FH        ; Modulo 128.
  314. decod4: or al,ah        ; or in parity
  315.     stosb            ; store the character
  316.     dec rptct        ; Repeat counter.
  317.     cmp rptct,0        ; Write out char again?
  318.     jg dcod41
  319.     jmp decod1        ; No, get next char.
  320. dcod41:    mov rptval,al        ; Save the char.
  321.     jmp dcod11        ; and loop to next char.
  322. decod5:    pop bx
  323.     pop dx            ; dx is pushed twice (really)
  324.     pop cx
  325.     pop dx
  326.     pop es
  327.     pop di
  328.     pop si
  329.     ret
  330. decod6:    mov bufpnt,di
  331.     pop dx
  332.     pop es
  333.     pop di
  334.     pop si
  335.     jmp rskp        ; Return successfully if done.
  336.  
  337.  
  338.  
  339.     ; output the buffer, reset bufpnt and chrcnt
  340.  
  341. outbuf: cmp flags.xflg,1    ; Writing to screen? [21c] 
  342.     je outbf2        ; Yes, handle specially. [21c] 
  343.     push bx
  344.     mov ah,writef        ; The write code.
  345.     mov dx,offset fcb
  346.     int dos            ; Write the record.
  347.     pop bx
  348.     cmp al,0        ; Successful.
  349.     jz outbf1
  350.     push ax            ; Remember the return code. [20d]
  351.     call abfil        ; Fix things up before aborting. [20d]
  352.     pop ax            ; Retrive return code. [20d]
  353.     cmp al,01
  354.     jz outbf0
  355.     call erpos
  356.     mov ah,prstr
  357.     mov dx,offset erms17    ; Record length exceeds dta.
  358.     int dos
  359.     ret
  360. outbf0: call erpos
  361.     mov ah,prstr        ; Tell about it.
  362.     mov dx,offset erms11    ; Disk full error.
  363.     int dos
  364.     ret
  365. outbf1:    add tfilsz+2,80H    ; Say 128 more characters received.
  366.     adc tfilsz,0
  367.     call kbpr        ; Print the kilobytes received.
  368.     call perpr        ; Print the percent ('?' for now).
  369. outb11:    mov bufpnt,offset buff    ; Addr for beginning.
  370.     mov chrcnt,dmasiz-1    ; Buffer size.
  371.     jmp rskp
  372. outbf2:    mov cx,dmasiz-1        ; Number of chars to write. [21c]
  373.     sub cx,chrcnt        ; minus # of unused in buffer
  374.     jle outb11        ; none to print, don't try
  375.     mov di,offset buff    ; Where they are. [21c]
  376.     call prtscr        ; Output buffer to screen. [21c]
  377.     jmp outb11        ; Reset counter & pointer. [21c]
  378.  
  379. ;  Tidy up before aborting.    [20d]
  380. ABFIL    PROC    NEAR
  381.     mov flags.xflg,1    ; Writing to screen?
  382.     je abfil0        ; Yes don't delete "file".
  383.     mov ah,closf        ; Close the file.
  384.     mov dx,offset fcb
  385.     int dos
  386.     cmp flags.abfflg,1    ; Delete what got across or keep it?
  387.     jne abfil0        ; Nope, keep it.
  388.     mov ah,delf        ; Delete it.
  389.     mov dx,offset fcb
  390.     int dos
  391. abfil0:    mov bx,offset erms10    ; Text of message to send.
  392.     call errpack        ; Send an error packet.
  393.     ret
  394. ABFIL    ENDP
  395.  
  396. ; General routine for sending an error packet.  Register BX should
  397. ; point to the text of the message being sent in the packet. [20f]
  398.  
  399. ERRPACK    PROC    NEAR
  400.     mov di,offset data    ; Where to put the message.
  401.     mov al,0
  402. errp1:    mov ah,[bx]
  403.     cmp ah,'$'        ; At end of message?
  404.     je errp2
  405.     inc al            ; Remember number of chars in msg.
  406.     mov [di],ah
  407.     inc bx
  408.     inc di
  409.     jmp errp1
  410. errp2:    mov ah,0
  411.     mov pack.argbk1,ax
  412.     mov ah,'E'        ; And send an error packet.
  413.     call spack
  414.      ret            ; Return if succeed or fail.
  415.     nop
  416.     nop
  417.     ret
  418. ERRPACK    ENDP
  419.  
  420. ;    Get the chars from the file.
  421.  
  422. gtchr:  cmp flags.filflg,0    ; Is there anything in the DMA?
  423.     jz gtchr0        ; Yup, proceed.
  424.     mov ah,rptq
  425.     mov origr,ah        ; Save repeat prefix here.
  426.     mov rptct,1        ; Number of times char is repeated.
  427.     mov rptval,0        ; Value of repeated char.
  428.     call inbuf
  429.      jmp gtchr1        ; No more chars, go return EOF.
  430.      nop            ; Make three bytes long.
  431. gtchr0:    mov bx,offset inbuf
  432.     jmp encode
  433. gtchr1:    mov ax,0ffffh
  434.     ret
  435.  
  436. ; encode - writes data portion of kermit packet into filbuf.
  437. ; expects BX to contain the address of a routine to refill the buffer,
  438. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  439. ; the maximum size of the data packet, bufpnt to contain a pointer to
  440. ; the source of the characters.
  441. ; Returns: AX/ the number of characters actually written to the buffer.
  442.  
  443. encode:    mov cl,trans.maxdat    ; Maximum packet size. [21b]
  444.     mov ch,0
  445.     mov di,offset filbuf    ; Where to put the data.
  446.     mov si,bufpnt        ; pointer into source buffer
  447.     mov dl,trans.rquote    ; send quote char
  448.     mov dh,0        ; assume no 8-bit quoting
  449.     cmp trans.ebquot,'N'    ; not doing 8-bit quoting
  450.     je encod1
  451.     cmp trans.ebquot,'Y'    ; or can but won't?
  452.     je encod1
  453.     mov dh,0ffh        ; remember we have to do it
  454. encod1: dec cx            ; Decrement output buffer counter.
  455.     jge encod2        ; Go on if there is more than one left.
  456.     sub di,offset filbuf
  457.     mov ax,di
  458.     mov bufpnt,si        ; update pointer into DMA.
  459.     jmp rskp
  460. encod2: cmp chrcnt,0        ; Any data in buffer?
  461.     jg encod3        ; yes, skip over buffer refill.
  462.     call bx            ; Get another buffer full.
  463.      jmp encod8
  464.     mov si,bufpnt        ; update position in DMA.
  465.     cmp chrcnt,0         ; no characters returned?
  466.     jne encod3        ; Got some, keep going.
  467.     jmp encod8        ; none, assume eof.
  468. encod3: dec chrcnt        ; Decrement input count.
  469.     lodsb
  470.         cmp flags.eofcz,0       ; Is a control-z an end of file? [27b]
  471.         je encd30               ; No, don't have to look for one. [27b]
  472.         cmp al,'Z'-40H          ; Is this a control-Z? [27b]
  473.         jne encd30              ; No, skip eof-processing. [27b]
  474.         mov flags.eoflag,0FFH   ; Yes, set eof flag. [27b]
  475.         jmp encod8              ; Go set character count and return. [27b]
  476. encd30: cmp rptq,0        ; Are we doing repeat prefixing? 
  477.     je encd3x        ; Nope, skip next part.
  478.     cmp chrcnt,0        ; Are we on the last character?
  479.     jle encd31        ; Yes, so there's no next character.
  480.     cmp rptct,94        ; Max number that we can put in a byte.
  481.     je encd31        ; Then that's it.
  482.     mov ah,[si]        ; Get the next character.
  483.     cmp al,ah        ; Is current char == next char?
  484.     jne encd31
  485.     inc rptct        ; Number of times char appears.
  486.     mov rptval,al        ; Remember the character.
  487.     inc cx            ; Repeats don't take up so much buffer space.
  488.     jmp encod1        ; Keep checking for more.
  489. encd31:    cmp rptct,1        ; Were previous characters repeats?
  490.     je encd3x        ; No, so just add this char.
  491.     cmp rptct,rptmin    ; Are we within bounds for repeat prefixing?
  492.     jge encd32        ; Yes, use repeat prefixing.
  493.     mov al,rptct
  494.     mov ah,0
  495.     sub si,ax        ; Not enough characters to warrant it.
  496.     mov rptval,0        ; Clear out this value.
  497.     inc cx            ; Adjust output buffer pointer.
  498.     mov al,rptq
  499.     mov origr,al        ; Save original repeat prefix.
  500.     mov rptq,0        ; Pretend we're not doing the prefixing.
  501.     mov al,rptct
  502.     mov ah,0
  503.     add chrcnt,ax        ; Adjust input buffer pointer.
  504.     jmp encod1        ; Reprocess those characters.
  505. encd32:    push ax            ; Do repeat prefixing - save data.
  506.     mov al,rptq        ; Add repeat prefix char.
  507.     stosb
  508.     dec cx            ; Account for it in buffer size.
  509.     mov al,rptct        ; Get the repeat count.
  510.     add al,20H        ; Make it printable.
  511.     stosb            ; Add to buffer.
  512.     dec cx
  513.     pop ax            ; Get back the actual character.
  514.     mov rptct,1        ; Reset repeat count.
  515.     mov rptval,0        ; And this.
  516. encd3x:    cmp dh,0        ; are we doing 8-bit quoting?
  517.     je encod4        ; no, forget this.
  518.     test al,80h        ; parity on?
  519.     je encod4        ; no, don't bother with this
  520.     and al,7fh        ; turn off parity
  521.     push ax            ; save original char for a bit
  522.     dec cx            ; decrement # of chars left
  523.     mov al,trans.ebquot    ; get quote char
  524.     stosb            ; save in buffer
  525.     pop ax            ; restore character
  526. encod4:    mov ah,al        ; save character
  527.     and ah,80h        ; only parity
  528.     and al,7fh        ; turn off parity in character
  529.     cmp al,' '        ; Compare to a space.
  530.     jl encod5        ; If less then its a control char.
  531.     cmp al,del        ; Is the char a delete?
  532.     jz encod5        ; Go quote it.
  533.     cmp al,dl        ; Is it the quote char?
  534.     je encod6        ; Yes - go add it. [21b start]
  535.     cmp dh,0        ; are we doing 8-bit quoting?
  536.     je encd41        ; no, don't translate it
  537.     cmp al,trans.ebquot    ; Is it the 8-bit quote char?
  538.     je encod6        ; Yes, just output with quote
  539. encd41:    cmp origr,0        ; Doing repeat prefixing?
  540.     je encod7        ; No, don't check for quote char.
  541.     cmp al,origr        ; Is this the repeat quote character.
  542.     je encod6        ; Yes, then quote it.
  543.     jmp short encod7    ; else don't quote it.
  544. encod5:    add al,40h        ; control char, uncontrollify
  545.     and al,7fh
  546. encod6:    push ax            ; save the char
  547.     dec cx
  548.     mov al,dl
  549.     stosb
  550.     pop ax
  551. encod7:    or al,ah        ; put parity back
  552.     stosb
  553.     cmp rptct,1        ; One occurence of this char?
  554.     jne encd7x
  555.     mov al,origr
  556.     mov rptq,al        ; Restore repeat quote char.
  557.     jmp encod1        ; Yes, so loop around for some more.
  558. encd7x:    dec rptct        ; Add another entry of this char.
  559.     jmp encod1        ; With quoting and all.
  560.  
  561. encod8: sub di,offset filbuf
  562.     or di,di
  563.     je encod9        ; Nope.
  564.     mov ax,di
  565.     jmp rskp
  566. encod9: mov ax,0FFFFH        ; Get a minus one.
  567.     ret
  568.  
  569.  
  570. inbuf:  mov ah,flags.eoflag    ; Have we reached the end?
  571.     cmp ah,0
  572.     jz inbuf0
  573.     ret            ; Return if set.
  574. inbuf0:    push si
  575.     push di
  576.     push dx
  577.     push bx            
  578.     push cx
  579.     mov bx,offset buff    ; Set the r/w buffer pointer.
  580.     mov bufpnt,bx
  581.     mov ah,readf        ; Read a record.
  582.     mov dx,offset fcb
  583.     int dos
  584.     mov cx,filsiz
  585.     cmp cx,0        ; Check for 128 chars or less left.
  586.     jne inbuf1        ; Still have data left.
  587.     mov ax,ds
  588.     mov es,ax
  589.     mov si,offset filsiz+2
  590.     mov di,offset bufhex
  591.     cmps filsiz+2,es:bufhex
  592.     ja inbuf1        ; More than 128 chars.
  593.     mov flags.eoflag,0FFH    ; Set End-of-file.
  594.     mov cx,filsiz+2
  595.     mov chrcnt,cx        ; Return proper number of chars.
  596.     mov flags.filflg,0    ; Buffer not empty.
  597.     pop cx
  598.     pop bx
  599.     pop dx
  600.     pop di
  601.     pop si
  602.     jmp rskp
  603. inbuf1:    sub filsiz+2,80H    ; Sent another 128 chars.
  604.     sbb filsiz,0        ; Account for the doubleword.
  605.     add tfilsz+2,80H    ; Book keeping for the same.
  606.     adc tfilsz,0
  607.     push ax
  608.     call kbpr        ; Print the kilobytes sent.
  609.     call perpr        ; Print the percent sent.
  610.     pop ax
  611.     mov al,80H        ; Use as counter for number of chars read.
  612.     pop cx
  613.     pop bx
  614.     pop dx
  615.     pop di
  616.     pop si
  617.     mov ah,0        ; Zero the flag (buffer not empty).
  618.     mov chrcnt,ax        ; Number of chars read from file.
  619.     mov flags.filflg,0    ; Buffer not empty.
  620.     jmp rskp
  621.  
  622. nulref:    mov chrcnt,0        ; No data to return.
  623.     jmp rskp
  624.  
  625. nulr:    ret
  626.  
  627. ; Print the number of Kilobytes transferred.
  628.  
  629. kbpr:    cmp flags.remflg,0    ; remote mode?
  630.     jne kbpr1        ; yes, no printing.
  631.     mov ax,tfilsz+2
  632.     mov bx,tfilsz
  633.     mov cl,10
  634.     shr ax,cl        ; divide by 1024
  635.     mov cl,6        ; high order moves 16-10 = 6 bits
  636.     shl bx,cl
  637.     or ax,bx
  638.     cmp ax,oldkbt        ; is it the same?
  639.     je kbpr1        ; yes, skip printing
  640.     mov oldkbt,ax        ; save new # of kb
  641.     push ax
  642.     call kbpos        ; Postion the cursor.
  643.     pop ax
  644.     call nout        ; Print the number of KBytes transferred.
  645. kbpr1:    ret
  646.  
  647. ; Print the percent transferred.
  648.  
  649. perpr:    cmp flags.remflg,0    ; remote mode?
  650.     jne perpr5        ; yes, no printing.
  651.     mov ax,tfilsz
  652.     or ax,tfilsz+2
  653.     cmp ax,oldper        ; same as it was before?
  654.     je perpr5        ; yes, don't bother printing.
  655.     mov oldper,ax        ; remember this for next time
  656.     cmp ofilsz,0        ; No divide by zeroes.
  657.     je perpr5        ; If not proceed.
  658.     cmp wrpmsg,0        ; did we write the percentage message?
  659.     jne perpr1        ; yes, skip this part
  660.     call perpos        ; position cursor
  661.     mov dx,offset permsg
  662.     mov ah,prstr
  663.     int dos            ; write out message
  664.     mov wrpmsg,1        ; init flag so we don't do it again
  665. perpr1:    call perpos        ; Position the cursor.
  666. perpr2:    mov dx,tfilsz        ; Get the high order word.
  667.     mov ax,tfilsz+2        ; Get the low order word.
  668.     div ofilsz        ; Div by percent adjusted original file size.
  669.     cmp ax,100        ; > 100% ?
  670.     jle perpr3        ; no, accept it
  671.     mov ax,100        ; else just use 100
  672. perpr3:    call nout
  673.     mov dl,'%'        ; Load a percent sign.
  674. perpr4:    mov ah,conout        ; Print the character.
  675.     int dos
  676. perpr5:    ret
  677.  
  678. getfil: mov ah,0FFH
  679.     mov flags.filflg,ah    ; Nothing in the DMA.
  680.     mov ax,0
  681.     mov flags.eoflag,ah    ; Not the end of file.
  682.     mov bx,offset fcb+0CH
  683.     mov [bx],ax        ; Zero the current block number.
  684.     mov bx,offset fcb+0EH
  685.     mov [bx],ax        ; Ditto for Lrecl.
  686.     mov bx,offset fcb+20H
  687.     mov [bx],ah        ; Zero the current record (of block).
  688.     inc bx
  689.     mov [bx],ax        ; Same for record (of file). 
  690.     mov bx,offset fcb+23H
  691.     mov [bx],ax
  692.     mov ah,openf        ; Open the file.
  693.     mov dx,offset fcb
  694.     int dos
  695.     mov dx,word ptr fcb+18    ; get file size (hi order word)
  696.     mov filsiz,dx
  697.     mov ax,word ptr fcb+16    ; lo order word
  698.     mov filsiz+2,ax
  699.     div percnt        ; Divide by 100.
  700.     mov ofilsz,ax
  701.     mov tfilsz,0        ; Set bytes sent to zero.
  702.     mov tfilsz+2,0
  703.     mov oldkbt,-1
  704.     mov oldper,-1
  705.     cmp filsiz,0        ; Null file?
  706.     jne getfl0        ; Nope.
  707.     cmp filsiz+2,0        ; Null file?
  708.     jne getfl0        ; Nope.
  709.     mov flags.eoflag,0FFH    ; Set EOF.
  710. getfl0:    jmp rskp
  711.  
  712.  
  713. gtnfil: cmp flags.cxzflg,'Z'    ; Did we have a ^Z? [20b]
  714.     je gtn5            ; If yes, we're done sending files. [20b]
  715.     cmp flags.wldflg,0    ; Was there a "*"?        [7 start]
  716.     je gtn5            ; Nope.
  717.     mov bx,offset cpfcb    ; Get FCB from last check for file.  
  718.     mov di,offset fcb    ; Copy to FCB.
  719.     mov cl,37        ; Size of FCB.
  720.     call fcbcpy
  721. gtn2:    mov ah,snext
  722.     mov dx,offset fcb    ; More files?
  723.     int dos
  724.     cmp al,0FFH
  725.     je gtn5
  726.     mov bx,offset fcb
  727.     mov di,offset cpfcb
  728.     mov cl,37
  729.     call fcbcpy        ; Copy from FCB.
  730.     mov di,offset fcb+1    ; Get name of next file to send.
  731.     mov bx,offset buff+1
  732.     mov cl,11
  733.     call fcbcpy
  734.     call getfil        ; Initialize
  735.      jmp r
  736.     jmp rskp            
  737. gtn5:    mov flags.wldflg,0    ; Reset wild card flag.
  738.     ret                         ;  [7 end]
  739.  
  740.  
  741. ;    Get the file name (including host to micro translation)
  742.  
  743. gofil:  cmp flags.xflg,1    ; Remote command? [21c]
  744.     jne goflx        ; No.... [21c]
  745.     jmp gofla        ; Yes so skip this stuff. [21c]
  746. goflx:    cmp flags.nmoflg,1    ; Overriding name from other side? [21a]
  747.     jne gofil0        ; No - get the filename. [21a]
  748.     jmp gofil7        ; Yes, so ignore packet contents. [21a]
  749. gofil0:    mov bx,offset data    ; Get the address of the file name. [21a]
  750.     mov fdtpnt,bx        ; Store the address.
  751.     mov bx,offset fcb+1    ; Address of the FCB.
  752.     mov fcbptr,bx        ; Save it.
  753.     mov ax,0
  754.     mov temp1,ax        ; Initialize the char count.
  755.     mov temp2,ax
  756.     cmp flags.droflg,1    ; Default drive? [21a]
  757.     je gofil1        ; No - don't blank out value in FCB. [21a]
  758.     mov si,offset fcb
  759.     mov [si],ah        ; Set the drive to default to current.
  760. gofil1: mov ch,' '        ; Moved the label. [21a]
  761.     mov [bx],ch        ; Blank the FCB.
  762.     inc bx
  763.     inc ah
  764.     cmp ah,0BH        ; Twelve?
  765.     jl gofil1
  766. gofil2: mov bx,fdtpnt        ; Get the NAME field.
  767.     mov ah,[bx]
  768.     inc bx
  769.     mov fdtpnt,bx
  770.     cmp ah,'.'        ; Seperator?
  771.     jne gofil3
  772.     mov bx,offset fcb+9H
  773.     mov fcbptr,bx
  774.     mov ax,temp1
  775.     mov temp2,ax
  776.     mov temp1,9H
  777.     jmp gofil6
  778. gofil3: cmp ah,0        ; Trailing null?
  779.     jz gofil7        ; Then we're done.
  780.     call verlet        ; Verify that the char is legal. 
  781.     mov bx,fcbptr
  782.     mov [bx],ah
  783.     inc bx
  784.     mov fcbptr,bx
  785.     mov ax,temp1        ; Get the char count.
  786.     inc ax
  787.     mov temp1,ax
  788.     cmp ax,8H        ; Are we finished with this field?
  789.     jl gofil2
  790. gofil4: mov temp2,ax
  791.     mov bx,fdtpnt
  792.     mov ah,[bx]
  793.     inc bx
  794.     mov fdtpnt,bx
  795.     cmp ah,0
  796.     jz gofil7
  797.     cmp ah,'.'        ; Is this the terminator?
  798.     jne gofil4        ; Go until we find it.
  799. gofil6: mov bx,fdtpnt        ; Get the TYPE field.
  800.     mov ah,[bx]
  801.     inc bx
  802.     mov fdtpnt,bx
  803.     cmp ah,0        ; Trailing null?
  804.     jz gofil7        ; Then we're done.
  805.     call verlet        ; Verify that the char is legal. 
  806.     mov bx,fcbptr
  807.     mov [bx],ah
  808.     inc bx
  809.     mov fcbptr,bx
  810.     inc temp1        ; Increment char count.
  811.     cmp temp1,0CH        ; Are we finished with this field?
  812.     jl gofil6
  813. gofil7:    cmp flags.remflg,0    ; remote mode?
  814.     jne gofil7a        ; yes, don't print it.
  815.     call prtfn        ; Print the file name. [21a]
  816. gofil7a:cmp flags.destflg,0    ; Writing to the printer?
  817.     jne gf7y
  818.     push es
  819.     mov ax,ds
  820.     mov es,ax        ; Set this up.
  821.     mov cx,11
  822.     mov si,offset printer
  823.     mov di,offset fcb
  824.     repne movsb        ; Change name in FCB to be printer.
  825.     pop es
  826.     jmp gofil9
  827. gf7y:    mov ah,flags.flwflg    ; Is file warning on?
  828.     cmp ah,0
  829.     jnz gf7x
  830.     jmp gofil9        ; If not, just proceed.
  831. gf7x:    mov ah,openf        ; See if the file exists.
  832.     mov dx,offset fcb
  833.     int dos
  834.     cmp al,0FFH        ; Does it exist?
  835.     jnz gf8x
  836.     jmp gofil9        ; If not create it.
  837. gf8x:    cmp flags.remflg,0    ; remote mode?
  838.     jne gf8xa        ; yes, skip printing
  839.     call frpos        ; Position cursor. 
  840.     mov ah,prstr        ; Inform the user we are renaming the file.
  841.     mov dx,offset infms5
  842.     int dos
  843. gf8xa:    mov ax,temp2        ; Get the number of chars in the file name.
  844.     cmp ax,0
  845.     jne gofil8
  846.     mov ax,temp1
  847.     mov temp2,ax
  848. gofil8: mov ch,0
  849.     mov cl,al
  850.     mov al,0        ; Says if first field is full.
  851.     cmp cl,9H        ; Is the first field full?
  852.     jne gofl81
  853.     mov al,0FFH        ; Set a flag saying so.
  854.     dec cl
  855. gofl81: mov bx,offset fcb    ; Get the FCB.
  856.     add bx,cx        ; Add in the character number.
  857.     mov ah,'&'
  858.     mov [bx],ah        ; Replace the char with an ampersand.
  859.     push ax
  860.     push bx
  861.     mov ah,openf        ; See if the file exists.
  862.     mov dx,offset fcb
  863.     int dos
  864.     pop bx
  865.     cmp al,0FFH        ; Does it exist?
  866.     pop ax
  867.     jz gofl89        ; If not create it.
  868.     cmp al,0        ; Get the flag.
  869.     jz gofl83
  870.     dec cl            ; Decrement the number of chars.
  871.     cmp cl,0
  872.     jz gofl88        ; If no more, die.
  873.     jmp gofl81
  874. gofl83: inc cl            ; Increment the number of chars.
  875.     cmp cl,9H        ; Are we to the end?
  876.     jl gofl81        ; If not try again ; else fail. 
  877.  
  878. gofl88:    cmp flags.remflg,0    ; remote mode?
  879.     jne gofl88a        ; yes, no printing
  880.     call erpos        ; Position cursor.
  881.     mov ah,prstr        ; Tell the user that we can't rename it.
  882.     mov dx,offset ermes4
  883.     int dos
  884. gofl88a:mov bx,dx        ; Tell host can't rename.  [20f]
  885.     call errpack        ; Send error packet before abort. [20f]
  886.     ret
  887.  
  888. gofl89:    cmp flags.remflg,0    ; remote mode
  889.     jne gofil9        ; yes, don't have to print it
  890.     mov bx,offset fcb+0CH    ; Point past the end of the file name.
  891.     mov dh,[bx]        ; Save the present contents.
  892.     mov ah,'$'
  893.     mov [bx],ah        ; Put in a dollar sign.
  894.     push dx
  895.     mov ah,prstr        ; Print the file name.
  896.     mov dx,offset fcb+1
  897.     int dos
  898.     pop dx
  899.     mov bx,offset fcb+0CH    ; Restore over the dollar sign.
  900.     mov [bx],dh
  901. gofil9: mov ah,delf        ; Delete the file if it exists.
  902.     mov dx,offset fcb
  903.     int dos
  904.     mov ax,0
  905.     mov si,offset fcb+0CH
  906.     mov [si],ax        ; Zero current block.
  907.     mov si,offset fcb+0EH
  908.     mov [si],ax        ; Same for Lrecl.
  909.     mov si,offset fcb+20H
  910.     mov [si],ah        ; Zero the current record (within block).
  911.     inc si
  912.     mov [si],ax        ; Zero record (within file).
  913.     mov si,offset fcb+23H
  914.     mov [si],ax
  915.     mov ofilsz,0        ; File size unknown.
  916.     mov tfilsz,0        ; Set bytes received to zero.
  917.     mov tfilsz+2,0
  918.     mov oldkbt,-1
  919.     mov oldper,-1
  920.     mov ah,makef        ; Now create it.
  921.     mov dx,offset fcb
  922.     int dos
  923.     cmp al,0FFH        ; Is the disk full?
  924.     je gf9x
  925.     jmp rskp
  926. gf9x:    cmp flags.remflg,0    ; remote mode?
  927.     jne gf9xa        ; yes, don't try printing
  928.     call erpos        ; Position cursor.
  929.     mov ah,prstr        ; If so tell the user.
  930.     mov dx,offset erms12
  931.     int dos
  932.     mov bx,dx
  933. gf9xa:    call errpack        ; Send an error packet.
  934.     ret
  935. gofla:  cmp pack.argbk1,0    ; Any data in "X" packet? [21c start]
  936.     je gofla1        ; Nothing to print. 
  937.     mov ah,prstr
  938.     mov dx,offset crlf
  939.     int dos    
  940.     int dos            ; Print another crlf.
  941.     mov di,offset data    ; Where data is.
  942.     mov cx,pack.argbk1    ; How much data we have.
  943.     call prtscr        ; Print it on the screen.
  944. gofla1:    mov ah,prstr
  945.     mov dx,offset crlf
  946.     int dos
  947.     jmp rskp        ; And done. [21c end]
  948. FILEIO    ENDP
  949.  
  950. ; Passed char of incoming filename in AH.  Verify that it is legal
  951. ; and if not change it to an "X".
  952. verlet:    cmp ah,'0'
  953.     jl ver2            ; See if it's a legal weird char.
  954.     cmp ah,'z'+1
  955.     jns ver2
  956.     cmp ah,'9'
  957.     jle ver1        ; It's between 0-9 so it's OK.
  958.     cmp ah,'A'
  959.     jl ver2            ; Coud be a weird char.
  960.     cmp ah,'Z'
  961.     jle ver1        ; It's A-Z so it's OK.
  962.     cmp ah,'a'
  963.     jl ver2
  964.     and ah,137O        ; It's a-z, capitalize.
  965. ver1:    ret
  966.  
  967. ver2:    push es
  968.     mov cx,ds
  969.     mov es,cx        ; Scan uses ES register.
  970.     mov di,offset spchar    ; Special chars.
  971.     mov cx,spclen        ; How many of them.
  972.     cmp dosnum,0        ; Under version 2.0
  973.     je ver3
  974.     mov di,offset spchar2
  975.     mov cx,spc2len
  976. ver3:    mov al,ah        ; Char is in al.
  977.     repnz scasb        ; Search string for input char.
  978.     pop es
  979.     mov ah,al        ; Return it in AH.
  980.     cmp cx,0        ; Was it there?
  981.     jnz ver1        ; Yes, return it.
  982.     mov ah,'X'        ; If illegal, replace with "X".
  983.     mov flags.nmoflg,1
  984.     ret
  985.  
  986. ; Print incoming filename(s). [21a]
  987. PRTFN    PROC    NEAR
  988.     call clrfln        ; Position cursor & blank out the line.
  989.     mov di,offset data    ; Where to put the name.
  990.     mov bx,offset fcb    ; Where it is now.
  991.     cmp flags.droflg,0    ; Drive specified?
  992.     je prtfn1
  993.     mov dl,[bx]        ; Which one did they say?
  994.     add dl,'@'        ; Make it readable.
  995.     mov ah,dconio        ; Print the drive name. 
  996.     int dos
  997.     mov dl,':'
  998.     int dos
  999. prtfn1:    inc bx            ; Point to start of filename.
  1000.     cmp flags.nmoflg,0    ; Is filename in packet?
  1001.     je prtfn2        ; no, keep going
  1002.     add di,pack.argbk1    ; bump by length of remote name
  1003.     mov si,offset asmsg    ; something to put after it
  1004.     mov cx,asmln        ; length of it
  1005.     rep movsb        ; add this to the buffer
  1006. prtfn2:    mov cx,8        ; At most 8 letters in file name.
  1007.     mov si,bx        ; this is source now
  1008. prtfn3:    lodsb            ; get a letter
  1009.     cmp al,' '        ; Done with name?
  1010.     je prtfn4        ; yes, continue
  1011.     stosb            ; else store
  1012.     loop prtfn3        ; and loop thru rest
  1013. prtfn4: mov si,offset fcb+9    ; Point to file type. 
  1014.     cmp byte ptr [si],' '    ; is there a type?
  1015.     je prtfn5        ; Nope so we're done.
  1016.     mov al,'.'        ; Add the dot.
  1017.     stosb
  1018.     mov cx,3        ; At most 3 letters in file type.
  1019.     rep movsb        ; copy type (incl trailing spaces)
  1020. prtfn5:    mov byte ptr [di],'$'    ; end the string
  1021.     mov ah,prstr        ; Print the file name.
  1022.     mov dx,offset data
  1023.     int dos
  1024.     mov flags.droflg,0    ; Reset flag once have the full name.
  1025.     mov flags.nmoflg,0
  1026.     ret
  1027. PRTFN    ENDP
  1028.  
  1029. ; Print data onto the screen.  If text has no "$" in it, just print
  1030. ; it.  Else, do special output for the "$".  
  1031. ; Routine expects: DI = Start of buffer we are to print.
  1032. ;           CX = Number of characters to print.     [21c]
  1033.  
  1034. PRTSCR    PROC    NEAR
  1035.     mov al,'$'        ; This is what we're looking for.
  1036.     mov oloc,di        ; Remember original buffer address. 
  1037.     mov osiz,cx        ; And original size. 
  1038.     push es
  1039.     mov bx,ds
  1040.     mov es,bx        ; Have ES point to data area.
  1041. prts0:    repnz scasb        ; Search for "$" in the buffer.
  1042.     cmp cx,0        ; Found one?
  1043.     je prts1        ; No, do a regular DOS call.
  1044.     mov ah,prstr
  1045.     mov dx,oloc        ; Print up to the "$". 
  1046.     int dos
  1047.     mov ah,dconio
  1048.     mov dl,'$'
  1049.     int dos            ; Print the "$"
  1050.     mov oloc,di        ; New starting location.
  1051.     mov osiz,cx        ; New size.
  1052.     jmp prts0
  1053. prts1:    mov bx,oloc        ; The buffer location.
  1054.     add bx,osiz        ; Point past the data.
  1055.     mov [bx],al        ; Add "$" for printing.
  1056.     mov ah,prstr
  1057.     mov dx,oloc
  1058.     int dos
  1059.     pop es
  1060.     ret
  1061. PRTSCR    ENDP
  1062.  
  1063. FIXFCB  PROC    NEAR    
  1064.     push ax            ; Don't forget this.  [22]
  1065.     mov bx,offset fcb+18
  1066.     mov di,offset filsiz
  1067.     mov ax,[bx]
  1068.     mov [di],ax
  1069.     mov bx,offset fcb+16
  1070.     mov ax,[bx]
  1071.     mov 2[di],ax
  1072.     pop ax            ; Get number of chars in last buffer full. [22]
  1073.     sub filsiz+2,ax        ; Get real file size.
  1074.     sbb filsiz,0
  1075.     mov bx,offset fcb+18
  1076.     mov di,offset filsiz
  1077.     mov ax,[di]
  1078.     mov [bx],ax
  1079.     mov bx,offset fcb+16
  1080.     mov ax,2[di]
  1081.     mov [bx],ax
  1082.     ret
  1083. FIXFCB    ENDP
  1084.  
  1085. ; Jumping to this location is like retskp.  It assumes the instruction
  1086. ;   after the call is a jmp addr.
  1087.  
  1088. RSKP    PROC    NEAR
  1089.     pop bp
  1090.     add bp,3
  1091.     push bp
  1092.     ret
  1093. RSKP    ENDP
  1094.  
  1095. ; Jumping here is the same as a ret.
  1096.  
  1097. R    PROC    NEAR
  1098.     ret
  1099. R    ENDP
  1100.  
  1101. code    ends
  1102.     end
  1103.